package com.laicunba.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Random;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.laicunba.event.SharedPacketEmptyEvent;
import com.laicunba.pojo.CashCouponDO;
import com.laicunba.pojo.SharedPacketDO;
import com.laicunba.pojo.SharedPacketItemDO;
import com.laicunba.pojo.UserDO;
import com.laicunba.service.CashCouponService;
import com.laicunba.service.SharedPacketItemService;
import com.laicunba.service.SharedPacketService;
import com.laicunba.service.UserService;
import com.laicunba.util.AssertUtil;
import com.laicunba.util.RedisUtil;
import com.laicunba.util.StringUtil;

@Service
public class SharedPacketServiceImpl extends BaseServiceImpl implements SharedPacketService, ApplicationEventPublisherAware {
	private static final int EXPIRE_TIME = 1000 * 60 * 60 * 24 * 3;
	@Autowired
	private UserService userService;
	@Autowired
	private CashCouponService cashCouponService;
	@Autowired
	private SharedPacketItemService sharedPacketItemService;

	private ApplicationEventPublisher publisher;

	@Override
	public boolean doShare(SharedPacketDO packetDO) {
		AssertUtil.assertNotNull(packetDO, "PACKET_NOT_EXIST");
		RedisUtil.incrBy("SHARED_PACKET.SplitCount." + packetDO.getId(), Long.parseLong(Integer.toString(packetDO.getSplitCount())));
		RedisUtil.set("SHARED_PACKET.amount." + packetDO.getId(), packetDO.getAmount().toString(), EXPIRE_TIME);
		RedisUtil.set("SHARED_PACKET.extractType." + packetDO.getId(), packetDO.getExtractType(), EXPIRE_TIME);
		return true;
	}

	@Override
	public SharedPacketItemDO extract(String packetId, String mobile) {
		String splitCountStr = RedisUtil.get("SHARED_PACKET.SplitCount." + packetId);
		String amountStr = RedisUtil.get("SHARED_PACKET.amount." + packetId);
		String extractType = RedisUtil.get("SHARED_PACKET.extractType." + packetId);
		if (StringUtil.isEmpty(splitCountStr, amountStr, extractType)) {
			AssertUtil.assertFail("NOT_EXIST_OR_EXPIRE");
		}
		String extractAmt = RedisUtil.get("SHARED_PACKET.mobile." + packetId + "." + mobile);
		if (StringUtil.isNotEmpty(extractAmt)) {
			SharedPacketItemDO itemDO = new SharedPacketItemDO();
			itemDO.setPacketId(packetId);
			itemDO.setMobile(mobile);
			itemDO.setAmount(BigDecimal.valueOf(Double.parseDouble(extractAmt)));
			return itemDO;
		}

		RedisUtil.set("SHARED_PACKET.mobile." + packetId + "." + mobile, "-1", EXPIRE_TIME);

		long splitCount = 0;
		BigDecimal amt = BigDecimal.ZERO;
		amt = BigDecimal.valueOf(Double.parseDouble(amountStr));
		splitCount = Long.parseLong(splitCountStr);
		// 拆红包
		if (splitCount <= 0 || amt.compareTo(BigDecimal.ZERO) <= 0) {
			return null;
		}
		RedisUtil.decrBy("SHARED_PACKET.SplitCount." + packetId, 1);
		SharedPacketItemDO itemDO = new SharedPacketItemDO();
		BigDecimal luckAmt = BigDecimal.ZERO;
		if (splitCount == 1) {
			luckAmt = amt;
			SharedPacketEmptyEvent event = new SharedPacketEmptyEvent(packetId);
			publisher.publishEvent(event);
		} else if (SharedPacketService.EXTRACT_TYPE_AVERAGE.equalsIgnoreCase(extractType)) {
			luckAmt = amt.divide(BigDecimal.valueOf(splitCount), RoundingMode.HALF_DOWN);
		} else if (SharedPacketService.EXTRACT_TYPE_RANDOM.equalsIgnoreCase(extractType)) {
			BigDecimal avgAmt = amt.divide(BigDecimal.valueOf(splitCount), RoundingMode.HALF_DOWN);
			luckAmt = avgAmt.multiply(BigDecimal.valueOf(new Random().nextDouble() * (splitCount > 3 ? 2 : 1))).setScale(2, BigDecimal.ROUND_HALF_DOWN);
			if (luckAmt.compareTo(amt) >= 0) {
				luckAmt = amt;
			}
		}
		splitCount--;
		amt = amt.subtract(luckAmt).setScale(2, BigDecimal.ROUND_HALF_DOWN);
		RedisUtil.set("SHARED_PACKET.amount." + packetId, amt.toString(), EXPIRE_TIME);
		RedisUtil.set("SHARED_PACKET.mobile." + packetId + "." + mobile, luckAmt.toString(), EXPIRE_TIME);
		itemDO.setMobile(mobile);
		itemDO.setPacketId(packetId);
		itemDO.setAmount(luckAmt);
		itemDO.setId(packetId + "." + mobile);
		AssertUtil.assertTrue(sharedPacketItemService.create(itemDO), "CREATE_ITEM_FAIL");
		make(itemDO);
		return itemDO;
	}

	@Transactional
	@Override
	public boolean make(SharedPacketItemDO sharedPacketItemDO) {
		if (sharedPacketItemDO == null) {
			return false;
		}
		UserDO userDO = userService.findByMobile(sharedPacketItemDO.getMobile());
		if (userDO == null) {
			return false;
		}
		if (sharedPacketItemDO.isUsed()) {
			AssertUtil.assertFail("PACKET_ITEM_USED");
		}
		SharedPacketDO packetDO = get(SharedPacketDO.class, sharedPacketItemDO.getPacketId());
		AssertUtil.assertNotNull(packetDO, "PACKET_NOT_EXIST");
		if ("CASH_COUPON".equalsIgnoreCase(packetDO.getType())) {

			CashCouponDO cashCouponDO = new CashCouponDO();
			cashCouponDO.setAmount(sharedPacketItemDO.getAmount());
			cashCouponDO.setConditions(packetDO.getConditions());
			cashCouponDO.setName(packetDO.getName());
			cashCouponDO.setBeginTime(new Date());
			cashCouponDO.setEndTime(new Date());
			cashCouponDO.getEndTime().setDate(cashCouponDO.getEndTime().getDate() + 15);
			cashCouponDO.setSummary(packetDO.getSummary());
			cashCouponDO.setUserId(userDO.getId());
			cashCouponDO.setUsedAmount(BigDecimal.ZERO);
			AssertUtil.assertTrue(cashCouponService.create(cashCouponDO), "CASH_COUPON_CREATE_FAIL");
			sharedPacketItemDO.setUsed(true);
			AssertUtil.assertTrue(sharedPacketItemService.updateSkipCheckOwner(sharedPacketItemDO), "UPDATE_PACKET_ITEM_FAIL");

			return true;

		}
		return false;
	}

	@Transactional
	@Override
	public void make(String mobile) {
		List<SharedPacketItemDO> sharedPacketItemDOList = sharedPacketItemService.findUseableByMobile(mobile);
		if (sharedPacketItemDOList == null || sharedPacketItemDOList.isEmpty()) {
			return;
		}
		for (SharedPacketItemDO itemDO : sharedPacketItemDOList) {
			make(itemDO);
		}
	}

	@Override
	public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
		publisher = applicationEventPublisher;

	}
}
